package com.guogee.dao;

import java.util.ArrayList;

import java.util.List;
import java.util.Map;


import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.guogee.db.DBHelper;
import com.guogee.util.Log;
import com.mongodb.AggregationOutput;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.CommandResult;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.WriteResult;

public abstract class ADao<T> {
	
	DBHelper dbHelper;
	DBCollection dbCollection;
	public static int ORDERBY_ASC = 1;
	public static int ORDERBY_DESC = -1;
	public ADao(){
		dbHelper = DBHelper.getInstance();
	}
	
	public abstract boolean insertItem(T obj);

	public List<T> getAllItem() {
		DBCursor cursor = dbCollection.find();
		List<T> list = new ArrayList<T>();
		while(cursor.hasNext()){
			list.add(parstItemFromCursor(cursor));
			
		}
		cursor.close();
		return list;
	
	}
	public abstract T parstItemFromCursor(DBCursor cursor);
	
	public abstract T parstDBObject(DBObject obj);

	public boolean deleteItemByFeiled(Map<String, Object> con) {
		DBObject dcon = new BasicDBObject(con);
		WriteResult result=dbCollection.remove(dcon);
		if(result==null){
			return false;
		}else{
			return checkWritenResult(result);
		}
	}	
	/**
	 * 只支持按order排序
	 * @param col
	 * @param con
	 * @param orderBy
	 * @return
	 */
	public  List<String> getDistinctField(String col,Map<String, Object> con,Map<String, Object> orderBy){
		BasicDBObject query = new BasicDBObject(con);
		BasicDBObject match = new BasicDBObject("$match",query);

		 DBObject sortFields = new BasicDBObject(orderBy);
		 DBObject sort = new BasicDBObject("$sort", sortFields );
//		 DBObject proFields = new BasicDBObject();
//		 proFields.put(col, 1);
//		 proFields.put("_id", 0);
//		 DBObject project = new BasicDBObject("$project", proFields );
		 DBObject groupFields = new BasicDBObject("_id","$"+col);
		 groupFields.put("order",new BasicDBObject( "$first", "$order"));
		 DBObject group = new BasicDBObject("$group", groupFields );
		 AggregationOutput output = dbCollection.aggregate(match,group, sort);
		 String result = output.getCommandResult().getString("result");
		 Log.i(result);
		 JsonArray jArray = new JsonParser().parse(result).getAsJsonArray();
		 List<String> list = new ArrayList<String>();
		 for(int i = 0; i < jArray.size(); i++){
			 JsonObject obj =jArray.get(i).getAsJsonObject();
			 list.add(obj.get("_id").getAsString());
			 
		 }
		 return list;
		
	}
	
	public  List<String> getDistinctField(String feiled,Map<String, Object> con){
		BasicDBObject query = new BasicDBObject(con);

		List<String> list = dbCollection.distinct(feiled, query);
		return list;
		
	}
	
	public  List<T> getItemByFields(Map<String, Object> con,Map<String, Integer> orderBy){
		List<T> result = new ArrayList<T>();
		BasicDBObject query = new BasicDBObject(con);
	
		DBCursor cursor = dbCollection.find(query);
		if(orderBy != null){
			BasicDBObject order = new BasicDBObject(orderBy);
			cursor.sort(order);
		}
		while (cursor.hasNext()) {
			 result.add(parstItemFromCursor(cursor));
		}
		cursor.close();
		return result;
	}
	
	/*
	 * 查找的个数
	 */
	public List<T> getItemByFieldsSize(Map<String, Object> con, Map<String, Integer> orderBy, int size) {
		List<T> result = new ArrayList<T>();
		BasicDBObject query = new BasicDBObject(con);

		DBCursor cursor = dbCollection.find(query).limit(size);
		if (orderBy != null) {
			BasicDBObject order = new BasicDBObject(orderBy);
			cursor.sort(order);
		}
		while (cursor.hasNext()) {
			result.add(parstItemFromCursor(cursor));
		}
		cursor.close();
		return result;
	}
	
	/**
	 * 分组查询
	 * @param con
	 * @param groupKey
	 * @return
	 */
	public List<T> getItemByFieldsGroupBy(Map<String, Object> con,Map<String, Boolean> groupKey,Map<String, Object> initialKey,String reduce){
		BasicDBObject condiction = new BasicDBObject(con);
		BasicDBObject key = new BasicDBObject(groupKey);
		BasicDBObject inital = new BasicDBObject(initialKey);
		BasicDBList groupList = (BasicDBList)dbCollection.group(key, condiction, inital,reduce);
		List<T> result = new ArrayList<T>();
		for(int i = 0; i < groupList.size(); i++){
			BasicDBObject obj=(BasicDBObject) groupList.get(i);  
			result.add(parstDBObject(obj)) ;
		}
		return result;
	}

	
	public boolean updateItemByFeiled(Map<String, Object> con,
			Map<String, Object> value) {
		// TODO Auto-generated method stub
		BasicDBObject update = new BasicDBObject(con);
	
		BasicDBObject updateTemp = new BasicDBObject(value);
		
		System.out.println(update.toString() + updateTemp.toString());
		int effectedRows = dbCollection.update(update,new BasicDBObject("$set", updateTemp), false, true).getN();
		if (effectedRows > 0)
			return true;
		else
			return false;
	}// Smither
	
	
	/**
	 * 把值添加到数组中
	 * @param con 查询条件
	 * @param value 值
	 * @return
	 */
	public boolean appendItemByFeiled(Map<String, Object> con,
			Map<String, Object> value) {
		// TODO Auto-generated method stub
		BasicDBObject update = new BasicDBObject(con);
		
		BasicDBObject updateTemp = new BasicDBObject(value);
		System.out.println(update.toString() + updateTemp.toString());
		int effectedRows = dbCollection.update(update,
				new BasicDBObject("$addToSet", updateTemp), false, true).getN();
		if (effectedRows > 0)
			return true;
		else
			return false;
	}// Smither
	
	
	public List<T> queryAll(Map<String, Object> con) {
		List<T> result = new ArrayList<T>();
		BasicDBObject query = new BasicDBObject(con);

		DBCursor cursor = dbCollection.find(query);
		while (cursor.hasNext()) {
			result.add(parstItemFromCursor(cursor));
		}
		cursor.close();
		return result;
	}

	public T queryOne(Map<String, Object> con) {
		BasicDBObject query = new BasicDBObject(con);
		DBObject object=dbCollection.findOne(query);
		if(object!=null){
			return  parstDBObject(object);
		}
		return null;
	}
	
	/**
	 * 检查写入是否成功
	 * @param result
	 * @return
	 */
	protected boolean checkWritenResult(WriteResult result){
		CommandResult cmd=result.getLastError();
        if (cmd != null && !cmd.ok()) {
            String message=cmd.getErrorMessage();
            System.out.println(message);
            return false;
        }
		return true;
	}
}
